#include "user_sid36_service.h"

#include "uds_service.h"
#include "user_uds.h"

uint8_t write_buf[100];

int16_t Transfer_data_Port(uint8_t *rec_buf, uint8_t *rsp_buf, uint16_t rec_len)
{

    int16_t                             ret;
    uint16_t                            temp, len;
    transfer_data_req_struct           *transf_data_req;
    transfer_data_positive_resp_struct *transf_data_pstv_resp;

    transf_data_req = (transfer_data_req_struct *)rec_buf;

    transf_data_pstv_resp = (transfer_data_positive_resp_struct *)rsp_buf;

    // memcpy((uint8_t*)&transf_data_req, rec_buf, rec_len);

    // 第一包开始初始化
    if (uds_status.uds_sid34_service.block_cnt_start_flag == 1) {

        uds_status.uds_sid36_service.block_cnt = 1;

        uds_status.uds_sid36_service.pack_cnt = 1;

        uds_status.uds_sid36_service.block_crc = CRC32_INIT_VALUE;

        uds_status.uds_sid34_service.block_cnt_start_flag = 0;

        temp = (uds_status.uds_sid34_service.flash_program_size / (TRANSFER_DATA_BLOCK_LEN - 2));

        uds_status.uds_sid36_service.pack_number =
            (uds_status.uds_sid34_service.flash_program_size % (TRANSFER_DATA_BLOCK_LEN - 2)) != 0
                ? (temp + 1)
                : temp;

        // USER_UDS_LOG("file_size:%x, %x\n", uds_status.uds_sid34_service.flash_program_size,
        // uds_status.uds_sid36_service.pack_number);
    }

    // 检查请求报文顺序
    if (uds_status.uds_sid34_service.request_download_service_finish_flag == 0) {

        ret = -NRC_REQUEST_SEQUENCE_ERROR;

        return ret;
    }

    // 检查请求报文长度是否合法
    if ((rec_len != TRANSFER_DATA_BLOCK_LEN) &&
        (uds_status.uds_sid36_service.pack_cnt != uds_status.uds_sid36_service.pack_number)) {

        ret = -NRC_TRANSFER_DATA_SUSPENDED;

        return ret;
    }

    // 检查块序列计数
    if (uds_status.uds_sid36_service.block_cnt != transf_data_req->data_block_serial_num) {

        ret = -NRC_WRONG_BLOCK_SEQUENCE_COUNTER;

        // USER_UDS_LOG("CNT:%d,%d\n",uds_status.uds_sid36_service.block_cnt,
        // transf_data_req.data_block_serial_num);

        return ret;
    }

    // 更新写buf
    memcpy(write_buf, transf_data_req->data_block, (TRANSFER_DATA_BLOCK_LEN - 2));

    // USER_UDS_LOG("pack:%x %x\n", uds_status.uds_sid36_service.pack_cnt, transf_data_req.data_block[0]);
    // 更新需要写的起始地址
    uds_status.uds_sid36_service.need_write_add =
        FLASH_ADDR_APP_CODE + ((uds_status.uds_sid36_service.pack_cnt - 1) * (TRANSFER_DATA_BLOCK_LEN - 2));

    if (uds_status.uds_sid36_service.pack_cnt != uds_status.uds_sid36_service.pack_number) {

        if (0 == user_flash_n_word_write(uds_status.uds_sid36_service.need_write_add,
                                         (uint32_t *)(write_buf), (TRANSFER_DATA_BLOCK_LEN - 2) / 4)) {

            ret = -NRC_GENERAL_PROGRAMMING_FAILURE;

            return ret;
        }

        // TODO:需要回读flash确认

        // 更新crc
        uds_status.uds_sid36_service.total_crc =
            crc32_check(write_buf, (TRANSFER_DATA_BLOCK_LEN - 2), uds_status.uds_sid36_service.block_crc);
        USER_UDS_LOG("APP2CRC:%x\n", uds_status.uds_sid36_service.total_crc);
    }

    else {

        // 剩余不足一包长度
        len = (uds_status.uds_sid34_service.flash_program_size -
               (uds_status.uds_sid36_service.pack_number - 1) * (TRANSFER_DATA_BLOCK_LEN - 2));

        // 四字节对齐
        len = ((len + FLASH_PROGRAM_SIZE - 1) / FLASH_PROGRAM_SIZE) * FLASH_PROGRAM_SIZE;

        if (0 == user_flash_n_word_write(uds_status.uds_sid36_service.need_write_add,
                                         (uint32_t *)(write_buf), len / 4)) {

            ret = -NRC_GENERAL_PROGRAMMING_FAILURE;

            return ret;
        }

        // TODO:需要回读flash确认

        uds_status.uds_sid36_service.total_crc =
            ~crc32_check(write_buf, len, uds_status.uds_sid36_service.block_crc);

        // USER_UDS_LOG("last pcak:%x\n", uds_status.uds_sid36_service.total_crc);
    }

    // 更新块crc
    uds_status.uds_sid36_service.block_crc = uds_status.uds_sid36_service.total_crc;

    // 准备响应数据
    transf_data_pstv_resp->positive_resp_id = USD_GET_POSITIVE_RSP(transf_data_req->sid);

    transf_data_pstv_resp->data_block_serial_num = uds_status.uds_sid36_service.block_cnt;

    // 块序列计数自动累加(溢出后重头开始，不需要判断)
    uds_status.uds_sid36_service.block_cnt++;

    uds_status.uds_sid36_service.pack_cnt++;

    ret = TRANSFER_DATA_RESP_LEN;

    return ret;
}
